package com.tuzhi.base.jpa.healper;

import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONArray;
import com.alibaba.fastjson2.JSONObject;
import com.tuzhi.base.jpa.domain.*;
import com.tuzhi.base.jpa.enums.QueryTypeEnum;
import com.tuzhi.base.jpa.enums.SortOrderEnum;
import com.tuzhi.util.CloneTzUtil;
import com.tuzhi.util.ListTzUtil;
import com.tuzhi.util.ObjectTzUtil;
import com.tuzhi.util.StringTzUtil;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.exception.ExceptionUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Set;

public class WhereConditionHelper {

    private static final Logger log = LoggerFactory.getLogger(WhereConditionHelper.class);

    private final static String queryPre_ = "TZ-";
    private final static String sortPre_ = "TZS-";
    private final static String separate = "-";

    public static WhereConditionBO build() {
        return new WhereConditionBO();
    }

    public static WhereConditionBO build(String propertyName, Object valObject) {
        return new WhereConditionBO().addQueryConditionBO(propertyName, valObject);
    }

    public static WhereConditionBO addQueryConditionBO(WhereConditionBO whereConditionBO, QueryConditionBO queryConditionBO) {
        whereConditionBO.getQueryList().add(queryConditionBO);
        return whereConditionBO;
    }

    /**
     * 根据请求参数和参数申明创建查询条件
     * @param whereStatementBO
     * @param reqMap
     * @return
     */
    public static WhereConditionBO trans(WhereStatementBO whereStatementBO, Map reqMap) {

        if (whereStatementBO == null) {
            throw new RuntimeException("没有申明参数规则whereStatementBO!");
        }

        List<QueryStatementBO> list = whereStatementBO.getQueryStatementBOList();
        List<QueryConditionBO> queryConditionBOList = new ArrayList<>();
        for (QueryStatementBO queryStatementBO : list) {
            QueryStatementBO cloneBO = CloneTzUtil.cloneObj(queryStatementBO);
            Object val = reqMap.get(cloneBO.getPropertyName());
            if (cloneBO.isPassNull() && (ObjectTzUtil.isNull(val) || StringTzUtil.isBlank(val + ""))) {
                continue;
            }
            if (cloneBO.getQueryTypeEnum() == QueryTypeEnum.between
                    || cloneBO.getQueryTypeEnum() == QueryTypeEnum.in
                    || cloneBO.getQueryTypeEnum() == QueryTypeEnum.notIn) {
                List objList = new ArrayList();
                if (val instanceof List) {
                    List tmpVals = (List) val;
                    for (Object tmpVal : tmpVals) {
                        objList.add(cloneBO.transClassVal(tmpVal));
                    }
                }
                cloneBO.setObjList(objList);
            } else {
                cloneBO.setObjValue(cloneBO.transClassVal(val));
            }
            queryConditionBOList.add(cloneBO);
        }

        List<SortConditionBO> sortConditionBOList = new ArrayList<>();
        List<String> sortColList = whereStatementBO.getSortColList();
        List sortCols = (List) reqMap.get("sortCols");
        if (ListTzUtil.isNotEmpty(sortCols)) {
            for (Object sortCol : sortCols) {
                Map sortColMap = (Map) sortCol;
                String sortName = (String) sortColMap.keySet().stream().findFirst().get();
                if (sortColList.contains(sortName)) {
                    sortConditionBOList.add(new SortConditionBO(sortName, sortColMap.get(sortName) + ""));
                }
            }
        }

        return new WhereConditionBO(queryConditionBOList, sortConditionBOList);
    }

    public static WhereConditionBO trans(String json) {
        return new WhereConditionBO(transList(json, QueryConditionBO.class), transList(json, SortConditionBO.class));
    }

    public static <T> List<T> transList(String json, Class<T> c) {
        return transList(json, c, null);
    }

    public static <T> List<T> transList(String json, Class<T> c, Set<String> filterSet) {
        List<T> list = new ArrayList<>();

        String pre = queryPre_;
        if (c == SortConditionBO.class) {
            pre = sortPre_;
        }

        try {
            JSONObject root = JSON.parseObject(json);
            for(Map.Entry<String, Object> entry : root.entrySet()) {
                String key = entry.getKey();
                if (key.startsWith(pre)) {
                    key = key.substring(pre.length());
                    String [] keys = StringUtils.split(key, separate, 3);
                    String propertyName = keys[0];
                    if (filterSet != null && !filterSet.contains(propertyName)) {
                        log.info("过滤属性{}", propertyName);
                        continue;
                    }
                    switch (keys.length) {
                        case 1:
                            if (c == SortConditionBO.class) {
                                addSortList(list, propertyName, entry.getValue() + "");
                            } else {
                                addQueryList(list, propertyName, QueryTypeEnum.equal.name(), entry.getValue(), null);
                            }
                            break;
                        case 2:
                            if (c == SortConditionBO.class) {
                                log.warn("排序参数拆分异常！{}", key);
                            } else {
                                addQueryList(list, propertyName, keys[1], entry.getValue(), null);
                            }
                            break;
                        case 3:
                            addQueryList(list, propertyName, keys[1], entry.getValue(), keys[2]);
                            break;
                        default:
                            log.warn("参数拆分异常！{}", key);
                            break;
                    }
                }
            }
        } catch (Exception e) {
            log.error("json解析异常！{}", ExceptionUtils.getStackTrace(e));
        }

        return list;
    }

    public static void addSort(WhereConditionBO whereConditionBO, String propertyName,
                               SortOrderEnum sortOrderEnum) {
        if (whereConditionBO != null) {
            List<SortConditionBO> list = whereConditionBO.getSortList();
            if (list == null) {
                list = new ArrayList<>();
            }
            addSortList(list, propertyName, sortOrderEnum.name());
        }
    }

    public static void addSortList(List list, String propertyName,
                                String sortType) {

        if (ListTzUtil.isEmpty(list)) {
            log.warn("addSortList传入list为空");
            return;
        }

        SortOrderEnum sortOrderEnum = SortOrderEnum.ACE;
        if (SortOrderEnum.DESC.name().equalsIgnoreCase(sortType)) {
            sortOrderEnum = SortOrderEnum.DESC;
        }

        for (Object o : list) {
            if (o instanceof SortConditionBO) {
                if (((SortConditionBO) o).getPropertyName().equals(propertyName)) {
                    log.warn("addSortList已经有排序属性，不能再添加" + propertyName);
                    return;
                }
            }
        }

        try {
            list.add(new SortConditionBO(propertyName, sortOrderEnum));
        } catch (IllegalArgumentException e) {
            log.warn("自动组装参数sortType={}异常!", sortType);
        }

    }

    private static void addQueryList(List list, String propertyName,
                                     String queryType, Object objValue, String valType) {

        valType = StringUtils.isBlank(valType)? "string" : valType;

        try {
            QueryTypeEnum queryTypeEnum = null;
            if (queryType.equalsIgnoreCase("eq")) {
                queryTypeEnum = QueryTypeEnum.equal;
            } else if ("notEq".equalsIgnoreCase(queryType)) {
                queryTypeEnum = QueryTypeEnum.notEqual;
            }else {
                queryTypeEnum = QueryTypeEnum.valueOf(queryType);
            }

            switch (queryTypeEnum) {
                case equal:
                case notEqual:
                case gt:
                    //大于
                case ge:
                    //大于等于
                case lt:
                    //小于
                case le:
                    //小于等于
                case isEmpty:
                    //小于等于
                case isNotEmpty:
                    //小于等于
                case like:
                case notLike:
                    list.add(new QueryConditionBO(propertyName, queryTypeEnum, objValue));
                    break;
                case in:
                case notIn:
                case between:
                    Class valClass = ObjectTzUtil.getClassByShortName(valType);
                    if (valClass == null) {
                        throw new IllegalArgumentException("值类型不正确valType=" + valType);
                    }
                    List<Object> objectList = new ArrayList<>();
                    if (objValue instanceof JSONArray) {
                        //------JSONArray
                        JSONArray jsonArray = (JSONArray) objValue;
                        if (!jsonArray.isEmpty()) {
                            for (int i = 0; i < jsonArray.size(); i++) {
                                Object jsonObject1=jsonArray.get(i);
                                objectList.add(ObjectTzUtil.parseObj(jsonArray.getString(i), jsonObject1.getClass()));
                            }
                        }
                    } else {
                        //------","分隔
                        String valString = objValue + "";
                        if (StringTzUtil.isNotBlank(valString)) {
                            String[] vals = StringTzUtil.split(valString, ",");
                            for (String tmpS : vals) {
                                objectList.add(ObjectTzUtil.parseObj(tmpS, valClass));
                            }
                        }
                    }
                    list.add(new QueryConditionBO(propertyName, queryTypeEnum, objectList));

                    break;
                default:
                    throw new IllegalArgumentException();
            }

        } catch (Exception e) {
            log.warn("自动组装参数queryType={}异常!", queryType);
            log.warn(ExceptionUtils.getStackTrace(e));
        }

    }

    public static void main(String[] args) {
//        String json = "{\"ZHF-name\":\"用户登录\",\"aaa\":222,\"ZHFS-id\":\"DESC\"}";
//        String json = "{\"ZHF-id-in\":[1,2],\"ZHF-attr2-between-Date\":[\"2022-02-02 10:10\",\"2022-02-02 10:20\"],\"aaa\":222,\"ZHFS-id\":\"DESC\"}";
//        String json = "{\"ZHF-toolId-in-long\":[5,6]}";
        String json = "{\"ZHF-toolId-in\":[5,6]}";
        List<QueryConditionBO> list = transList(json, QueryConditionBO.class);
        System.out.println(list);
        List<SortConditionBO> list2 = transList(json, SortConditionBO.class);
        System.out.println(list2);

    }

}
